package com.gitee.pagekit.utils;

import com.gitee.pagekit.Page;
import com.gitee.pagekit.PageCache;
import com.gitee.pagekit.PageProperties;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author wxy
 * @version 1.0
 * @date 2024/5/11 18:18
 */
public class PageUtil {

    public static void initPage(Page page, PageProperties pageProperties){
        if(page == null || pageProperties == null){
            return;
        }
        if(page.getPageNum() == null){
            page.setPageNum(pageProperties.getPageNum());
        }
        if(page.getPageSize() == null){
            page.setPageSize(pageProperties.getPageSize());
        }
    }

    public static MappedStatement processCountMappedStatement(MappedStatement ms, String newMsId, PageCache pageCache) throws Exception {
        // TODO: 2024/5/11 newMsId
        List<ResultMap> newResultMaps = new ArrayList<ResultMap>(), oldResultMaps = ms.getResultMaps();
        String msId = ms.getId();
        ResultMap resultMap = new ResultMap.Builder(ms.getConfiguration(), ms.getId(), Long.class, Collections.emptyList()).build();
        newResultMaps.add(resultMap);
        ReflexUtil.setByFieldName(MappedStatement.class, ms, "resultMaps", newResultMaps);
        //id与缓存相关必须修改，否则会影响之后的分页结果
        ReflexUtil.setByFieldName(MappedStatement.class, ms, "id", newMsId);
        pageCache.setResultMaps(oldResultMaps);
        pageCache.setMappedStatementId(msId);
        return ms;
    }


    public static Long executeCountSql(String countSql , Executor executor, MappedStatement countMs,
                                Object parameter, BoundSql boundSql,
                                ResultHandler resultHandler, PageCache pageCache) throws Exception {
        final String sql = boundSql.getSql();
        CacheKey countKey = executor.createCacheKey(countMs, parameter, RowBounds.DEFAULT, boundSql);
        ReflexUtil.setByFieldName(BoundSql.class, boundSql, "sql", countSql);
        //执行 count 查询
        Object countResultList = executor.query(countMs, parameter, RowBounds.DEFAULT, resultHandler, countKey, boundSql);
        //重置
        ReflexUtil.setByFieldName(MappedStatement.class, countMs, "resultMaps", pageCache.getResultMaps());
        ReflexUtil.setByFieldName(MappedStatement.class, countMs, "id", pageCache.getMappedStatementId());
        ReflexUtil.setByFieldName(BoundSql.class, boundSql, "sql", sql);
        if (countResultList == null || ((List) countResultList).isEmpty()) {
            return 0L;
        }
        return ((Number) ((List) countResultList).get(0)).longValue();
    }


    public static List<Object> execPage(String pageSql, BoundSql boundSql, MappedStatement mappedStatements
                , RowBounds rowBounds, Executor target, Object objet, ResultHandler resultHandler, CacheKey cacheKey) throws Exception {
        String sql = boundSql.getSql();
        ReflexUtil.setByFieldName(BoundSql.class, boundSql, "sql", pageSql);
        List<Object> result = target.query(mappedStatements, objet, rowBounds, resultHandler, cacheKey, boundSql);
        ReflexUtil.setByFieldName(BoundSql.class, boundSql, "sql", sql);
        return result;
    }
}
